﻿using System;
using System.Collections.Generic;
using System.IO;
using Schematrix;

namespace UnrarService
{
    public class Entpacker
    {
        #region Porperties/Member
        /// <summary>
        /// Eine Liste aus Passworten die durchgegangen wird.
        /// </summary>
        public List<string> Password { get; set; }

        /// <summary>
        /// Der AktuellePasswortstring
        /// </summary>
        public string CurrentPassword { get; set; }

        /// <summary>
        /// Der Zielpfad wohin die Datei entpackt werden soll
        /// </summary>
        public string DestinationPath { get; set; }
        #endregion

        #region Konstruktor
        public Entpacker(string destinationPath)
        {
            DestinationPath = destinationPath;
        }
        #endregion

        #region Functions/Subs
        /// <summary>
        /// Entpacken der übergebenen Datei inkl. Filepath
        /// </summary>
        /// <param name="filePath">Pfad inkl. Dateiname der entpackt werden soll</param>
        /// <returns>TRUE->Entpacken erfolgreich | FALSE->Entpacken fehlgeschlagen</returns>
        public Boolean Entpacken(string filePath)
        {
            //Erst prüfen ob die Datei schon entpackt wurde
            if (!CheckIfFileExists(filePath))
            {
                Unrar unrar = new Unrar();
                Console.WriteLine("Unrar aufgerufen");

                foreach (string ePassword in Password)
                {
                    CurrentPassword = ePassword;
                    try
                    {
                        //Handler hinzufügen, wenn ein passwort gefordert wird
                        unrar.PasswordRequired += UnrarPasswordRequired;
                        unrar.DestinationPath = DestinationPath;
                        //Methode angeben was gemacht werden soll beim Open
                        unrar.Open(filePath, Unrar.OpenMode.Extract);

                        //Whileschleife ist notwendig um das Archiv zu entpacken
                        while (unrar.ReadHeader())
                        {
                            unrar.Extract();
                        }
                        return true;
                    }
                    catch (Exception ex)
                    {
                        //Wenn das passwort nicht richtig ist, dann können die unterschiedlichsten Fehlermeldungen kommen, einfach mit dem nächsten PW fortsetzen
                        continue;
                    }
                    finally
                    {
                        unrar.Close();
                    }
                }

                //Wenn bis hierher kein Return aufgerufen wurde, dann hat das Entpacken nicht funktioniert.
                return false;
            }

            return true;
        }

        /// <summary>
        /// Überprüft, ob die Datei bereits entpackt wurde.
        /// </summary>
        /// <returns>TRUE->Die Datei existiert schon | False->Datei existiert noch nicht</returns>
        private Boolean CheckIfFileExists(string filePath)
        {
            Unrar unrar = new Unrar();

            try
            {
                //Das Archiv nur zum auflisten öffnen
                unrar.Open(filePath, Unrar.OpenMode.List);

                while (unrar.ReadHeader())
                {
                    string currentFile = unrar.CurrentFile.FileName;

                    //Prüfen ob das Verzeichnis oder die Dateien schon existieren und wenn nicht wird beim ersten nicht gefundenen Wert False zurückgegeben
                    if (!(File.Exists(Path.Combine(DestinationPath, currentFile)) || Directory.Exists(Path.Combine(DestinationPath, currentFile))))
                    {
                        return false;
                    }

                    //Keine Dateien entpacken, sondern nur überspringen, da nur die Dateien herausgesucht werden sollen.
                    unrar.Skip();
                }
            }
            catch (Exception)
            {
                return false;
            }
            finally
            {
                unrar.Close();
            }

            return true;
        }

        #endregion

        #region Events
        /// <summary>
        /// Eventhandler der aufgerufen wird, wenn ein Passwort für das Archiv benötigt wird.
        /// </summary>
        private void UnrarPasswordRequired(object sender, PasswordRequiredEventArgs e)
        {
            e.Password = CurrentPassword;
            e.ContinueOperation = true;
        }
        #endregion

    }
}
